<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  function deepClone(obj, hash = new WeakMap()) {
    // 处理基本类型和null
    if (obj === null || typeof obj !== 'object') {
      return obj;
    }

    // 处理循环引用
    if (hash.has(obj)) {
      return hash.get(obj);
    }

    // 处理Date对象
    if (obj instanceof Date) {
      return new Date(obj);
    }

    // 处理RegExp对象
    if (obj instanceof RegExp) {
      return new RegExp(obj);
    }

    // 处理Set对象
    if (obj instanceof Set) {
      const clone = new Set();
      hash.set(obj, clone); // 关联
      obj.forEach(value => {
        clone.add(deepClone(value, hash));
      });
      return clone;
    }

    // 处理Map对象
    if (obj instanceof Map) {
      const clone = new Map();
      hash.set(obj, clone); // 关联
      obj.forEach((value, key) => {
        clone.set(deepClone(key, hash), deepClone(value, hash));
      });
      return clone;
    }

    // 处理数组或普通对象
    const clone = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj));

    hash.set(obj, clone); // 关联

    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        clone[key] = deepClone(obj[key], hash);
      }
    }

    return clone;
  }

  const obj = {
    a: '1',
    b: false,
    c: [1, '2'],
    d: new Date(),
    e: new RegExp('\d+'),
    g: new Set([2, { a: 1 }]),
    h: new Map([
      ['a', 3]
    ])
  }
  // 循环引用场景
  obj.f = obj
  obj.g.add(obj)
  obj.h.set('b', obj)

  console.log(deepClone(obj))

</script>
</body>
</html>